# -*- coding: utf-8 -*-
"""
Module Description: 赛季相关

Date: 2020/12/17
Author: sxj
"""
from datetime import datetime
from collections import defaultdict

from pyshare.const.enums.activity import ActivityType
from pyshare.const.enums.item import ItemType
from pyshare.const.enums.role import HeadFrameType
from pyshare.const.lang.tips_info import TipsInfo
from pyshare.dal.gameconfig.game_env import get_config_env_set
from pyshare.dal.gameconfig.query import getProfile, getProfileList
from pyshare.utils.time_utils import getCT, strToDatetime, addTimes, strToDate
from pyshare.dal.repository_impl import CrossSeasonRingRepository, \
    CrossSeasonActivityRepository, RoleRepository, CrossSeasonCelebrationRepository, CrossSeasonCfgRepository, \
    CrossSeasonServerRepository, ServerInfoRepository, ItemRepository, CrossSeasonDanCfgRepository, \
    CenterRedUnLimitRepository, CenterRedUnLimitReceiveRepository, CrossSeasonStageAwardCfgRepository, \
    CrossSeasonConstantRoleRepository, CrossSeasonPageantActivityRepository
from pyshare.redis_cache.cross.cross_season_cache import CrossSeasonHashCache
from pyshare.const.enums.chat import MsgType, Channel, SeasonChatPushLabel
from pyshare.utils import push_utils
from pyshare.remote_services.cross_chat_service import ChatService
from pyshare.const.enums.cross_season_enum import GLOBAL_SEASON_CFG_ID, \
    SeasonServerStatus, AwardStatus, SeasonPageantType
from common.service_config import get_app_id, get_server_id
from pyshare.core.context import temporary_ctx
from pyshare.bll.utils.cross.activity_utils import get_award_index


def convert_ring(seq, ring):
    """
    将赛季的递增轮次转换为阶段,小轮次

    :param list seq: 赛季排期配置
    :param int ring: 轮次
    """
    start = 1
    # eg. [[1,2], [3,4], [5]]
    new_seq = []
    for n in seq:
        temp = []
        for _ in range(n):
            temp.append(start)
            start += 1

        new_seq.append(temp)

    for stage_id, sub_seq in enumerate(new_seq, start=1):
        if ring in sub_seq:
            ring_id = sub_seq.index(ring) + 1
            return stage_id, ring_id

    return None, None


def get_season_base_info(current_time=None, need_award_time=True):
    """
    根据时间获取赛季基础信息

    NOTE: 当赛季重叠时,返回正在进行中的赛季

    :param datetime current_time: 当前时间
    :param need_award_time: 是否需要判断赛季领奖期
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    season_id = None
    stage_id = None
    ring_id = None

    # 赛季轮次
    season_ring = CrossSeasonRingRepository.get_by_current_time(current_time)
    if season_ring:
        season_id = season_ring.season_id
        stage_id = season_ring.stage_id
        ring_id = season_ring.ring_id
    else:
        # 赛季进行期
        season = CrossSeasonActivityRepository.get_current_season(current_time)
        if season:
            season_id = season.season_id
            # 赛季所有的轮次
            rings = CrossSeasonRingRepository.filter_by_season_id(season_id)

            # 构造阶段时间范围{stage_id: {start_time: "", end_time: ""}}
            stage_dict = {}
            # 构造轮次时间范围{ring_id: {start_time: "", end_time: ""}}
            ring_dict = {}
            for ring in rings:
                if ring.stage_id in stage_dict:
                    if ring.start_time < stage_dict[ring.stage_id]["start_time"]:
                        stage_dict[ring.stage_id]["start_time"] = ring.start_time

                    if ring.end_time > stage_dict[ring.stage_id]["end_time"]:
                        stage_dict[ring.stage_id]["end_time"] = ring.end_time
                else:
                    stage_dict[ring.stage_id] = {"start_time": ring.start_time,
                                                 "end_time": ring.end_time}

                ring_dict[ring.ring_id] = {
                    "start_time": ring.start_time,
                    "end_time": ring.end_time,
                }

            # 构造轮次空白时间数据
            pre_ring_dict = defaultdict(dict)
            for i in ring_dict:
                if (i - 1) > 0:
                    pre_ring_dict[i - 1]["start_time"] = ring_dict[i - 1]["end_time"]
                    pre_ring_dict[i - 1]["end_time"] = ring_dict[i]["start_time"]

            # 构造阶段空白时间数据
            pre_stage_dict = defaultdict(dict)
            for i in stage_dict:
                if (i - 1) > 0:
                    pre_stage_dict[i - 1]["start_time"] = stage_dict[i - 1]["end_time"]
                    pre_stage_dict[i - 1]["end_time"] = stage_dict[i]["start_time"]

                # 阶段内
                if stage_dict[i]["start_time"] <= current_time < stage_dict[i]["end_time"]:
                    stage_id = i

            # 查询当前阶段外时间
            if not stage_id:
                for i in pre_stage_dict:
                    if pre_stage_dict[i]["start_time"] <= current_time < pre_stage_dict[i]["end_time"]:
                        stage_id = i
                        break

            # 如果还没有阶段id,则取最大阶段
            if not stage_id:
                stage_id = max(stage_dict.keys())

            # 查询轮次外时间
            for i in pre_ring_dict:
                if pre_ring_dict[i]["start_time"] <= current_time < pre_ring_dict[i]["end_time"]:
                    ring_id = i
                    break

        # 赛季领奖期
        elif need_award_time:
            season = CrossSeasonActivityRepository.get_by_award_time(current_time)
            if season:
                season_id = season.season_id
                stage_id = len(season.season_schedule)
                ring_id = sum(season.season_schedule)

    return season_id, stage_id, ring_id


def is_server_join_season(server_id, current_time=None):
    """
    判断区服是否加入赛季活动
    :param server_id: 区服id
    :param current_time: 当前时间
    :return:
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    is_join_season = False

    season_server = CrossSeasonServerRepository.get_by_server_id(server_id)
    if (season_server
            and (season_server.server_status > SeasonServerStatus.NotJoined)
            and (current_time >= season_server.joined_time)):
        is_join_season = True
    return is_join_season


def is_ring_first_day(season_id, ring_id, current_time=None):
    """
    判断当前是否为该轮第一天
    :param season_id: 赛季id
    :param ring_id: 阶段id
    :param current_time: 当前时间
    :return:
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    is_first_day = False
    ring_record = CrossSeasonRingRepository.get_by_season_ring_id(season_id, ring_id)
    if ring_record and ring_record.start_time:
        sub_day = (current_time - ring_record.start_time).days
        if sub_day == 0:
            is_first_day = True

    return is_first_day


def get_day_of_season(current_time=None):
    """
    根据时间判断赛季的第几天

    :param datetime current_time: 当前时间
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    nday = None

    # 赛季
    season = CrossSeasonActivityRepository.get_current_season(current_time)
    if season:
        nday = (current_time - season.start_time).days + 1

    return nday


def get_group_of_season_stage(season_id, stage_id, rid, server_id):
    """
    获取赛季阶段分区id

    :param int season_id: 赛季id
    :param int stage_id: 阶段id
    :param str rid: 角色id
    :param int server_id: 角色区服id
    """
    season_hash_cache = CrossSeasonHashCache()

    group_id = None
    user = "{}|{}".format(rid, server_id)

    stage_data = season_hash_cache.get_user_season_stage_data(
        season_id=season_id,
        stage_id=stage_id,
        user=user,
    )
    if stage_data and ("rank_key" in stage_data):
        group_id = int(stage_data["rank_key"].rsplit(":", -1)[-1])

    return group_id


def get_season_stage_award_time(current_time=None):
    """
    根据时间获取阶段领奖时间

    :param datetime current_time: 当前时间
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    season_ring = CrossSeasonRingRepository.get_stage_award_time(current_time)

    # 是否为阶段领奖期
    status = False
    season_id = None
    stage_id = None

    # 阶段生成结束时间
    group_end_time = None

    if season_ring:
        status = True
        season_id = season_ring.season_id
        stage_id = season_ring.stage_id
        group_end_time = season_ring.group_end_time

    return status, season_id, stage_id, group_end_time


def get_season_award_time(current_time=None):
    """
    根据时间获取赛季领奖时间

    :param datetime current_time: 当前时间
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    season = CrossSeasonActivityRepository.get_by_award_time(current_time)

    # 是否为阶段领奖期
    status = False
    season_id = None

    if season:
        status = True
        season_id = season.season_id

    return status, season_id


def get_cross_activity_data(server_id, season_id, ring_id):
    """
    获取区服的赛季相关跨服活动数据

    活动数据格式:
        {
            "activity_id": "",
            "activity_status": "",
            "start_time": "",
            "end_time": "",
            "award_end_time": "",
            "server_list": "",
        }

    :param int server_id: 区服id
    :param int seasion_id: 赛季id
    :param int ring_id: 轮次id eg. 配置 [2, 2] 那么轮次1->4
    :return: 跨服活动列表
    """
    season_hash_cache = CrossSeasonHashCache()

    return season_hash_cache.get_cross_activity_data(
        server_id=server_id,
        season_id=season_id,
        ring_id=ring_id,
    )


def get_seasons(current_time=None):
    """
    获取当前时间内的赛季活动

    :param datetime current_time: 当前时间
    """
    if not current_time:
        current_time = getCT()
    else:
        current_time = strToDatetime(current_time)

    seasons = []
    # 先筛选领奖期的赛季活动
    season = CrossSeasonActivityRepository.get_by_award_time(current_time, "SeasonId", "StartTime", "EndTime",
                                                             "AwardEndTime", "SeasonSchedule")
    if season:
        season_dict = {"SeasonId": season.season_id, "StartTime": season.start_time, "EndTime": season.end_time,
                       "AwardEndTime": season.award_end_time, "SeasonSchedule": season.season_schedule}
        seasons.append(season_dict)

    season = CrossSeasonActivityRepository.get_current_season(current_time,  "SeasonId", "StartTime", "EndTime",
                                                              "AwardEndTime", "SeasonSchedule")
    if season:
        season_dict = {"SeasonId": season.season_id, "StartTime": season.start_time, "EndTime": season.end_time,
                       "AwardEndTime": season.award_end_time, "SeasonSchedule": season.season_schedule}
        seasons.append(season_dict)

    return seasons


def get_season_server_warm_status(server_id):
    """
    获取区服赛季预热状态

    :param int server_id: 区服id
    """
    # 赛季活动配置id有且只为1
    season_cfg = CrossSeasonCfgRepository.get_by_cfgid(cfg_id=GLOBAL_SEASON_CFG_ID)
    # 没配置,不显示预热
    if not season_cfg:
        return False

    # 在排除区服内,不显示预热
    if server_id in season_cfg.exclude_server_list:
        return False

    now = getCT()

    # 没有开服时间
    app_id = get_app_id()
    with temporary_ctx(app_id=app_id, server_id=server_id):
        open_date = ServerInfoRepository.get_by_envkey('ServerOpeningDate')
        # 没开服时间,不显示预热
        if not open_date:
            return False

    open_date = datetime.combine(strToDate(open_date.env_value), datetime.min.time())

    # 时间未到第一赛季预热开始时间,不开预热
    if now < season_cfg.old_server_warm_time:
        return False

    # 在赛季1预热时间内,所有区服都是预热期
    elif season_cfg.old_server_warm_time <= now < season_cfg.open_time:

        # 开服时间不到,不显示预热
        if addTimes(open_date, days=season_cfg.new_server_warm_days) > now:
            return False
        else:
            return True

    # 大于1赛季预热结束时间
    else:
        # 赛季区服数据
        season_server = CrossSeasonServerRepository.get_by_server_id(server_id)
        # 未加入赛季的
        if not season_server:
            # 区服多少天后预热
            if addTimes(open_date, days=season_cfg.new_server_warm_days) > now:
                return False
            else:
                return True
        # 临时加入的
        else:
            # 只要加入,且时间未到达,显示预热
            if ((season_server.server_status > SeasonServerStatus.NotJoined)
                    and (now < season_server.joined_time)):
                return True
            else:
                return False


def update_season_user_stage_score(season_id, stage_id, rid, server_id, score):
    """
    更新赛季玩家阶段积分

    :param season_id: 赛季id
    :param stage_id: 阶段id
    :param rid: 角色rid
    :param server_id: 区服id
    :param score: 积分
    """
    season_hash_cache = CrossSeasonHashCache()
    user = "{}|{}".format(rid, server_id)

    data = season_hash_cache.get_user_season_stage_data(
        season_id=season_id,
        stage_id=stage_id,
        user=user,
    )

    if not data:
        data = {"score": score}
    else:
        data.update({"score": score})

        from pyshare.utils.season_rank_utils import season_rank_utils

        if "rank_key" in data:
            group_id = int(data["rank_key"].rsplit(":", -1)[-1])
            season_rank_utils.update_season_group_rank(
                rid=rid,
                server_id=server_id,
                season_id=season_id,
                stage_id=stage_id,
                group_id=group_id,
                score=score,
            )

    # 缓存
    season_hash_cache.cache_season_stage_data(
        season_id=season_id,
        stage_id=stage_id,
        user=user,
        data=data,
    )


def check_season_msg(season_id, rid, is_check_end_time=False, cur_time=None, need_ring=False, role_record=None):
    """
    校验赛季信息
    :param season_id: 赛季id
    :param rid: 角色id
    :param is_check_end_time:  是否校验赛季结束时间在当前时间之后
    :param cur_time:  当前时间
    :param need_ring: 是否需要当前轮次数据
    :param role_record: 玩家角色信息
    :return: {校验状态，分区id，当前阶段} （状态为False时弹出tips,tips字段名为info；无分区资格时分区id为None）
    """
    if not cur_time:
        cur_time = getCT()
    result = dict()
    season = CrossSeasonActivityRepository.get_by_season_id(season_id)
    # 赛季是否存在
    if not season:
        result["Status"] = False
        result["Info"] = TipsInfo.ActivityKeys.ActivityNotFound
        return result
    # 赛季是否开始
    if (not season.start_time) or (season.start_time > cur_time):
        result["Status"] = False
        result["Info"] = TipsInfo.CrossSeason.CrossSeasonActivityNotStart
        return result
    # 当前时间是否在领奖结束时间之前
    if season.award_end_time and (season.award_end_time < cur_time):
        result["Status"] = False
        result["Info"] = TipsInfo.CrossSeason.CrossSeasonActivityIsAwardEnd
        return result
    # 当前时间是否在结束时间之前
    if is_check_end_time:
        if season.end_time and (season.end_time < cur_time):
            result["Status"] = False
            result["Info"] = TipsInfo.CrossSeason.CrossSeasonActivityIsEnd
            return result
    # 查询玩家是否拥有总榜资格
    if not role_record:
        role_record = RoleRepository.get_by_rid(rid, "RoleLv", "SrvId")
    if not role_record:
        result["Status"] = False
        result["Info"] = TipsInfo.RoleKeys.dataError
        return result
    limit_cfg = getProfile("TcActivityLimitCfg", ActivityType=ActivityType.CrossSeason)
    if not limit_cfg:
        result["Status"] = False
        result["Info"] = TipsInfo.RoleKeys.configError
        return result
    if role_record.role_lv < limit_cfg.RoleLvLimit:
        result["Status"] = False
        result["Info"] = TipsInfo.CrossSeason.CrossSeasonRoleLvLimit
        return result
    cur_season, stage_id, ring_id = get_season_base_info(cur_time)
    # 传入赛季不是当前赛季 阶段id从赛季记录表读取
    if cur_season != season_id:
        stage_id = len(season.season_schedule)
    if need_ring:
        # 查询当前阶段与轮次
        result["RingId"] = ring_id

    if stage_id:
        # 当前处于活动开始的第几天
        result["CurDayN"] = (cur_time - season.start_time).days + 1

    # 查询玩家分区 无分区资格时返回None
    result["GroupId"] = get_group_of_season_stage(season_id, stage_id, rid, role_record.srv_id)
    result["StageId"] = stage_id
    result["SeasonData"] = season
    result["Status"] = True
    return result


def check_celebrate_msg(rid, season_id, cur, celebrate_id=None, check_season=True):
    """
    庆典基础校验
    :param rid:
    :param season_id:
    :param cur:
    :param celebrate_id:
    :param check_season:
    :return:
    """
    result = {}
    # 玩家角色信息
    role_record = RoleRepository.get_by_rid(rid, "RoleLv", "SrvId")
    if not role_record:
        result["Status"] = False
        result["Info"] = TipsInfo.RoleKeys.dataError
        return result
    if check_season:
        # 赛季信息校验
        result = check_season_msg(season_id, rid, is_check_end_time=False, role_record=role_record)
        if not result.get("Status", False):
            return result
    # 庆典校验
    if not celebrate_id:
        celebrate = CrossSeasonCelebrationRepository.get_season_cur_celebrate(season_id)
    else:
        celebrate = CrossSeasonCelebrationRepository.get_by_celebrate_id(celebrate_id)
    if not celebrate or celebrate.season_id != season_id:
        result = {"Status": False, "Info": TipsInfo.CrossSeason.CrossSeasonCelebrateNotExist}
        return result
    if celebrate.start_time > cur:
        result = {"Status": False, "Info": TipsInfo.CrossSeason.CrossSeasonCelebrateNotOpen}
        return result
    if celebrate.end_time < cur:
        result = {"Status": False, "Info": TipsInfo.CrossSeason.CrossSeasonCelebrateHasClose}
        return result
    # 参与庆典等级校验
    role_lv_limit = get_config_env_set("CrossSeasonCelebrationLimit")
    if not role_lv_limit:
        result["Status"] = False
        result["Info"] = TipsInfo.RoleKeys.configError
        return result
    if rid != celebrate.role_guid and role_record.role_lv < role_lv_limit:
        result["Status"] = False
        result["Info"] = TipsInfo.CrossSeason.CrossSeasonCelebrateRoleLvLimit
        return result
    result.update({"Celebration": celebrate.asdict()})
    return result


def send_system_msg(channel, season_id, server_id=None, ext=None):
    """
    发送系统消息
    :param channel: 仅支持season和world频道
    :param season_id: 赛季id
    :param server_id: 世界频道发送的区服id
    :param ext: 扩展字段信息,dict
    :return:
    """
    if not ext:
        ext = {}

    uid = 'season'
    rid = 'system'

    team_id = ''
    if channel == Channel.Season:
        team_id = 'season_chat'
        server_record = CrossSeasonServerRepository.get_rand_server()
        if not server_record:
            return

        server_id = server_record.server_id

        # 添加聊天信息
        res_data, req_data = ChatService.add_chat_msg(channel, uid, rid, alln_id=str(season_id), msgtype=MsgType.text,
                                                      content={"text": ' '}, ext=ext, garb_filter=1, team_id=team_id,
                                                      srv_id=server_id)

    elif channel == Channel.World:
        res_data, req_data = ChatService.add_chat_msg(channel, uid, rid, alln_id=str(season_id), msgtype=MsgType.text,
                                                      content={"text": ' '}, ext=ext, garb_filter=1, team_id=team_id)

    # 推送消息
    def after_send_msg(rtn, req, channel):
        if not rtn:
            return False, "ChatMsgNotReturn"

        if rtn and rtn["stat"] == 1:
            rtn = rtn["data"]
            req_data = req["data"]
            # 格式化消息字段
            msg = {"RoleGuid": req_data["role_id"],
                   "UserId": req_data["user_id"],
                   "MsgType": req_data["msg_type"],
                   "Time": str(datetime.fromtimestamp(req_data["time"])),
                   "Id": rtn["_id"],
                   "Ext": req_data["ext"],
                   'DeviceId': req_data['device_id'],
                   "ServerId": req["server_id"],
                   "Channel": channel,
                   "Text": rtn["text"],
                   "Team": req_data['alliance']}
            # 推送消息
            if channel == Channel.Season:
                label = SeasonChatPushLabel.Season
                push_utils.call_push_data_to_label(
                    label=label,
                    push_id=push_utils.PushId.CHAT_MSG,
                    data=msg
                )
            elif channel == Channel.World:
                push_utils.call_push_data_to_all(
                    push_id=push_utils.PushId.CHAT_MSG,
                    data=msg,
                    server_id=server_id
                )
            return True

    after_send_msg(res_data, req_data, channel)


def check_lottery_red(role_data):
    """
    赛季抽奖红点
    :param role_data:
    :return:
    """
    if not role_data:
        return False
    item_lottery_cfg = getProfile("TcItemCrossSeasonLottery", SeasonId=role_data.season_id)
    item_lottery = ItemRepository.get_by_rid_itemtype_itemid(role_data.role_guid, ItemType.CrossSeasonLottery,
                                                             item_lottery_cfg.Id)
    # 是否有赛季抽奖券
    if item_lottery and item_lottery.count > 0:
        return True
    else:
        return False


def check_dan_upgrade_red(role_data):
    """
    段位晋升奖励红点
    :param role_data:
    :return:
    """
    if not role_data:
        return False
    dan_cfg_list = CrossSeasonDanCfgRepository.filter_by_seasonid(role_data.season_id)
    for dan_cfg in dan_cfg_list:
        # 奖励段位小于等于角色段位 且奖励段位不在角色已领取段位奖励中
        if dan_cfg.dan_id <= role_data.dan and (dan_cfg.dan_id not in role_data.upgrade_award_status):
            return True
    return False


def check_choose_clothes_red(role_data):
    """
    仙王殿时装红点
    :param role_data:
    :return:
    """
    if not role_data:
        return False
    if role_data.is_get_clothes:
        return False
    from pyshare.utils.season_rank_utils import season_rank_utils
    rank, score = season_rank_utils.get_season_rank_score(role_data.role_guid, role_data.server_id,
                                                          role_data.season_id)
    clothes_cfg_list = getProfileList("TcItemClothes", ActivityType=ActivityType.CrossSeason)
    for clothes_cfg in clothes_cfg_list:
        if rank in clothes_cfg.GetRank and clothes_cfg.ForeverUnlockTimes:
            return True
    return False


def check_season_un_limit_red(role_data):
    """
    限时不限量红包红点
    :param role_data:
    :return: True: 玩家有未领取红包
    """
    if not role_data:
        return False

    # 当前所有未失效红包
    cur_red_set = {c.red_guid for c in CenterRedUnLimitRepository.filter_not_expired_red()}

    if not cur_red_set:
        return False

    # 玩家已领取红包
    receive_red_set = {c.red_guid for c in
                        CenterRedUnLimitReceiveRepository.filter_by_rid_red_guid_list_column(role_data.role_guid,
                                                                                             list(cur_red_set),
                                                                                             'RedGuid')}
    # 有未领取红包
    if (cur_red_set - receive_red_set):
        return True
    return False


def check_rank_award_red(role_data, cur_time):
    """
    赛季总榜单奖励领取红点
    :param role_data:
    :param cur_time:
    :return: True: 玩家有未领取榜单奖励
    """
    from pyshare.utils.season_rank_utils import season_rank_utils

    if not role_data:
        return False

    status, award_season_id = get_season_award_time(current_time=cur_time)
    if not status:
        # 当前无领奖期
        return False

    if status and award_season_id != role_data.season_id:
        # 当前领奖期赛季与传入赛季不同
        return False

    if status and award_season_id == role_data.season_id:
        if (role_data.season_has_award == AwardStatus.Award) \
                or (role_data.season_has_award == AwardStatus.EmailAward):\
            # 已领奖
            return False
        rank, _ = season_rank_utils.get_season_rank_score(role_data.role_guid, role_data.server_id,
                                                              role_data.season_id)
        season_record = CrossSeasonActivityRepository.get_by_season_id(role_data.season_id)
        if not season_record:
            return False
        range_list = season_record.range_list
        award_index = get_award_index(rank, range_list)
        if award_index > -1:
            # 有未领取奖励
            return True

    return False


def check_group_rank_award_red(role_data, cur_time):
    """
    分赛区榜榜单奖励红点
    :param role_data:
    :param cur_time:
    :return: True: 玩家有未领取榜单奖励
    """
    from pyshare.utils.season_rank_utils import season_rank_utils

    if not role_data:
        return False

    status, award_season_id, award_stage_id, group_end_time = get_season_stage_award_time(current_time=cur_time)
    if not status:
        # 无领奖期赛季
        return False

    if status and role_data.season_id != award_season_id:
        # 领奖期赛季与查看的赛季不同
        return False

    group_id = get_group_of_season_stage(role_data.season_id, award_stage_id, role_data.role_guid, role_data.server_id)
    if not group_id:
        # 玩家未加入分赛区
        return False

    rank, _ = season_rank_utils.get_season_group_rank_score(role_data.role_guid, role_data.server_id,
                                                            role_data.season_id, award_stage_id, group_id)
    if role_data.stage_has_award >= award_stage_id:
        # 已领奖
        return False

    stage_cfg = CrossSeasonStageAwardCfgRepository.get_by_season_stage_id(role_data.season_id, award_stage_id)
    if not stage_cfg:
        return False
    range_list, award_list = stage_cfg.range_list, stage_cfg.award_list
    award_index = get_award_index(rank, range_list)
    if award_index > -1:
        # 有未领取奖励
        return True

    return False


def check_all_rank_award_red(role_data):
    """
    获取榜单领奖红点
    :param role_data:
    :return: True: 总榜或分赛区榜有未领取奖励
    """
    cur_time = getCT()

    # 总榜红点
    rank_red = check_rank_award_red(role_data, cur_time)

    # 分赛区榜红点
    group_rank_red = check_group_rank_award_red(role_data, cur_time)

    if rank_red or group_rank_red:
        return True
    return False


def check_constant_and_pageant_red(role_data):
    """
    连续性奖励红点、盛会红点
    :param role_data:
    :return:
    """
    constant_red = False    # 连续性红点
    pageant_red = False     # 盛会红点（针对举办者）
    if role_data:
        cur_time = getCT()
        constant_role = CrossSeasonConstantRoleRepository.get(role_data.role_guid)
        if constant_role:
            season_list = CrossSeasonActivityRepository.filter_column_order_by_season_id_end_time(cur_time, 1, 1)
            if season_list:
                # 获取正在举办的盛会
                pageant_record = None
                pageant_records = CrossSeasonPageantActivityRepository.filter_by_rid(role_data.role_guid, getCT())
                if pageant_records:
                    pageant_record = pageant_records[0]
                # 结算的赛季一致
                season_record = season_list[0]
                if season_record.season_id == constant_role.settle_season_id:
                    dan_cfg = getProfile("TcCrossSeasonDan", DanId=constant_role.settle_season_dan)
                    if dan_cfg:
                        constant_count = constant_role.constant_dan_dict.get(str(dan_cfg.VastDan))
                        constant_cfg = getProfile("TcCrossSeasonConstantAward", VastDan=dan_cfg.VastDan,
                                                  ConstantCount=constant_count)
                        #  连续性红点
                        if constant_cfg and constant_count not in constant_role.constant_award_stat:
                            constant_red = True
                        # 盛会可举办红点
                        if not pageant_record and constant_cfg:
                            if constant_cfg.PageantType == SeasonPageantType.Normal:
                                if constant_role.normal_pageant_count > 0:
                                    pageant_red = True
                            elif constant_cfg.PageantType ==  SeasonPageantType.Advance:
                                if constant_role.advance_pageant_count > 0:
                                    pageant_red = True
                # 档位可领取奖励
                if not pageant_red and pageant_record:
                    pageant_red = check_pageant_stage_red(pageant_record, pageant_record.hold_stage_award_stat)

    res_dict = dict()
    res_dict["ConstantAwardRed"] = constant_red
    res_dict["PageantRed"] = pageant_red
    return res_dict


def change_season_head_frame(server_id):
    """
    摘除赛季段位头像框
    :return:
    """
    with temporary_ctx(server_id=server_id):
        # 查询赛季段位头像框配置
        head_frame_cfg_list = getProfileList("TcItemHeadFrame", ConditionType=HeadFrameType.CrossSeasonDan)
        head_frame_list = [head_frame_cfg.ItemId for head_frame_cfg in head_frame_cfg_list]
        # 查询佩戴赛季头像框玩家
        role_list = RoleRepository.filter_by_head_frame_id_list(head_frame_list)
        role_dict = {role.role_guid: role for role in role_list}
        rid_list = role_dict.keys()
        # 更新玩家缓存
        server_id = get_server_id()
        server_rid_dict = {server_id: rid_list}
        role_dict = {}
        from pyshare.bll.utils.share.share_role_information import ShareRoleInformation
        role_cache_dict = ShareRoleInformation.get_many_role_information_from_cache_db(server_rid_dict)
        for rid, role_data in role_cache_dict.iteritems():
            role_data = role_data._asdict()
            # 头像框设置为默认值
            role_data['head_frame_id'] = 1
            role_dict[rid] = role_data
        ShareRoleInformation.set_many_role_information(role_dict)

        # 更新玩家头像框
        RoleRepository.update_by_head_frame_id_list(head_frame_list)

        return {}


def get_last_season_id(cur_time=None):
    """
    获取上赛季id(当前时间大于end_time)
    :param cur_time:
    :return:
    """
    if not cur_time:
        cur_time = getCT()

    last_season_id = None

    season_list = CrossSeasonActivityRepository.filter_column_order_by_season_id_end_time(cur_time, 1, 1, 'SeasonId')
    if len(season_list) > 0:
        season_record = season_list[0]
        last_season_id = season_record.season_id
    return last_season_id


def check_pageant_stage_red(pageant_act_record, stage_award_stat):
    """
    检测盛会阶段红点
    :return:
    """
    pageant_type = pageant_act_record.pageant_type
    stage_award_red = False
    # 检测阶段奖励未领取
    pageant_stage_cfg_dict = {}  # 阶段配置表
    stage_cfgs = getProfileList("TcCrossSeasonPageantStage", order_by="PageantType, StageId")
    for stage_cfg in stage_cfgs:
        if stage_cfg.PageantType not in pageant_stage_cfg_dict:
            pageant_stage_cfg_dict[stage_cfg.PageantType] = [stage_cfg]
        else:
            pageant_stage_cfg_dict[stage_cfg.PageantType].append(stage_cfg)
    stage_cfgs = pageant_stage_cfg_dict.get(pageant_type, [])
    for stage_cfg in stage_cfgs:
        # 检测红点
        if pageant_act_record.attend_count >= stage_cfg.AttendNum:
            if stage_cfg.StageId not in stage_award_stat:
                stage_award_red = True
                break
        else:
            break
        if stage_award_red:
            break
    return stage_award_red
